home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 130_01 / ry.c < prev    next >
Text File  |  1985-03-09  |  24KB  |  899 lines

  1. /********************************************************************
  2.     ry.c - library of file handlers
  3. */
  4.  
  5. /* changes */
  6.  
  7. /*
  8.     following applies to rx package, father of ry:
  9.  
  10.     7/25/81- put this file on seperate development disk, ALL 
  11.     development to this package to be done here only. crl files
  12.     may be spread around as needed.
  13.  
  14.     7/7/81-    made ropen() free allocated buffer space before
  15.     returning on ERROR. Don't close files that return ERROR
  16.     from ropen().
  17.  
  18.     7/7/81- made rclose do primitive close even if buffer not
  19.     flushed correctly, insuring that fd is always freed.
  20.  
  21.     8/18/81- corrected to be grammatically identical to unix
  22.     call syntax (almost, still additional arg to ropen and rcreat
  23.     to explicitly set file buffer size).
  24.  
  25.     2/14/82- add stderr, virtual console, virtual modem, and
  26.     vcon & vmodem to rgetc() and rputc().
  27.  
  28.     3/16/82- remove virtual stuff.
  29.  
  30.     5/30/82 - remove 'byte' and 'string' defines from code
  31.  
  32.     5/30/82 - change all 'FILE' to 'RFILE' for ver 1.46
  33.  
  34.     6/7/82 - fix ropen() setting of fp->_bufbase to '= fp + 1'
  35.  
  36.     7/14/82 - fix rclose to free memory AFTER using fd to free file
  37.  
  38.     9/9/82 - add bs (binary search file) code to package.  got it from
  39.                 bs.c, not fron cnlib, will save cnlib for a while...
  40.             no, maybe I did get it from cnlib....
  41.  
  42.     end of comments/changes on rx stuff
  43.  
  44. */
  45.  
  46. /*
  47.     following applies to ry package:
  48.  
  49.     9/11/82 - change over to ry disk, rename rx files to ry for starters, etc.
  50.                 change fseek() and ftell() to work with 'long' int
  51.                 rename them to lseek() and ltell(), respectively.
  52. */
  53.  
  54. #include "a:std.h"        /* bdscio.h + my stuff */
  55. #include <ry.h>            /* stuff for this package */
  56.  
  57. /*
  58.     purge any old copies, creat and open 'filename', buffer
  59. size equal to secs * size of one sector, mode of write (from
  60. beginning of file), append (write at end of file), or direct
  61. (read or write, starting at beginning of file, random access
  62. to any part of file). read not allowed as you can't read a
  63. new file.
  64. */
  65.  
  66. RFILE *        /* returns pointer to RFILE struct, or ERROR on error */
  67. rcreat(filename, mode, secs)
  68. char *filename;
  69. char mode;
  70. int secs;
  71. {
  72.     int fd;
  73.     char dummy_h[SECSIZ];
  74.     RFILE *ropen();
  75.  
  76.     setmem(dummy_h, SECSIZ, 0);                                /* nulls */
  77.     switch (mode) {
  78.     case 'r':    return ERROR;                        /* can't read empty file */
  79.     case 'w':
  80.     case 'a':
  81.     case 'd':
  82.         if ((fd = creat(filename)) == ERROR ) return ERROR;
  83.         if (write(fd, dummy_h, 1) != 1) {
  84.             fabort(fd);
  85.             return ERROR;                                    /* dummy header */
  86.         }
  87.         if (close(fd) == ERROR) return ERROR;                /* free up fd */
  88.         return ropen(filename, mode, secs);                    /* open */
  89.     default:
  90.         return ERROR;
  91.     }
  92. }
  93. /*
  94.     open 'filename' buffer in space provided by alloc(), setup
  95. fp, buffer of size SECSIZ * secs
  96. */
  97.  
  98. RFILE *        /* returns pointer to RFILE or ERROR on error */
  99. ropen(filename, mode, secs)
  100. char *filename;
  101. char mode;
  102. int secs;
  103. {
  104.     RFILE *fp;
  105.     int fd;
  106.     char *alloc();
  107.     unsigned rcfsiz(), rsrec();
  108.  
  109.     switch (mode) {
  110.     case 'r':                            /* read mode */
  111. /*        fd = open(filename, 0);            /* open read */
  112.         break;
  113. */
  114.     case 'w':                            /* write mode */
  115. /*    case 'a':                            /* append mode */ not supported yet */
  116.     case 'd':                            /* direct or random */
  117.         fd = open(filename, 2);            /* open r/w */
  118.         break;
  119.     default: return ERROR;
  120.     }
  121.     if (fd == ERROR) return ERROR;        /* open error */
  122.  
  123.     if ((fp = alloc(((secs + 1) * SECSIZ) + sizeof(*fp))) == 0) return ERROR;
  124.                                     /* no room for buffer */
  125.     fp -> _rfd = fd;                            /* file descriptor */
  126.     fp -> _bufbase = fp + 1;                    /* start of file buffer */
  127.     fp -> _bufbase += SECSIZ;                    /* room for header */
  128.     fp -> _secs = secs;                            /* secs. in buffer */
  129.     fp -> _nxtbyt = fp -> _bufbase;                  /* start at begin of buf */
  130.     fp -> _pastbuf = fp -> _bufbase + (secs * SECSIZ); /* endbuf */
  131.     fp -> _mode = mode;
  132. /** 'a' not supported yet...
  133.     fp -> _frstsec = (mode == 'a') ?            /* if 'a' start at end */
  134.         rcfsiz(fp->_rfd) : rsrec(fp->_rfd);     /* else at 0 */
  135. **/
  136.     if (read(fd, fp + 1, 1) < 0) {                /* get file header into core */
  137.         free(fp);
  138.         return ERROR;
  139.     }
  140.     fp -> _frstsec = rsrec(fp->_rfd);            /* start at sector 1 */
  141.     if (_fillbuf(fp) == ERROR ) {                /* fill the buffer */
  142.         free(fp);
  143.         return ERROR;
  144.     }
  145.     return fp;
  146. }
  147.  
  148. /*
  149.     flushes, then closes the random file at fp
  150. */
  151.  
  152. rclose(fp)            /* return -1 on error */
  153. RFILE *fp;
  154. {
  155.     int err_flag;
  156.  
  157.     err_flag = _rflush(fp);                                    /* flush buffer */
  158.     if (seek(fp->_rfd, 0, 0) == ERROR) err_flag = ERROR;    /* get to sec 0 */
  159.     if (write(fp->_rfd, fp+1, 1) != 1) err_flag = ERROR;    /* update header */
  160.     if (close(fp->_rfd) == ERROR) err_flag = ERROR;            /* close it */
  161.     free(fp);                                            /* free buffer space */
  162.     return err_flag;                                    /* did it flush ok? */
  163. }
  164. /*
  165.     fills buffer pointed at by fp->_bufbase, with file fp->_rfd,
  166. with fp->_secs sectors, starting with cp/m random record field
  167. lseek calls this after updating cp/m's rrf and fp's pointers (if
  168. necessary because seek is out of buffer area)
  169. */
  170.  
  171. _fillbuf(fp)            /* return -1 on error, 0 if OK */
  172. RFILE *fp;
  173. {
  174.     int fd, secs, got;
  175.     char *base;
  176.     unsigned rseek();
  177.  
  178.     fd = fp -> _rfd;
  179.     secs = fp -> _secs;
  180.     base = fp -> _bufbase;
  181.  
  182. /* call rread for sectors till buffer full or ERROR */
  183.     /* try to read all of buffer */
  184.     while  (secs -= (got = rread(fd, base, secs))) {
  185.         if ((got > 1000) OR (got == -1)) return ERROR;
  186.                                 /* unwritten random sector in buffer area */
  187.         setmem((base += (got * SECSIZ)), SECSIZ, 0);
  188.                                             /* fill this sector with 0's */
  189.         base += SECSIZ;                        /* inc. buffer ptr */
  190.         rseek(fd, 1, 1);                    /* inc. file ptr */
  191.         --secs;                                /* this one filled with 0 */
  192.     }                                        /* try filling rest of buffer */
  193.     fp -> _update = NO;                        /* clear update flag */
  194.     return OK;
  195. }
  196. /*
  197.     flushes the buffer fp->_bufbase if open for writing AND
  198. fp->_update shows the buffer has indeed been written to since
  199. last _fillbuf call. ignores flushes of i/o devices
  200. */
  201.  
  202. _rflush(fp)            /* return -1 on error, 0 if OK */
  203. RFILE *fp;
  204. {
  205.     unsigned rseek();
  206.  
  207.     if ((fp < 4) OR (fp->_mode == 'r') OR (fp->_update == NO))
  208.         return OK;                                            /* don't bother */
  209.     if (rseek(fp -> _rfd,fp -> _frstsec, 0) == ERROR) return ERROR;
  210.                                         /* seek first bufferd sec and ... */
  211.     if (rwrite(fp->_rfd, fp->_bufbase, fp->_secs) != fp->_secs)
  212.         return ERROR;                    /* ...write entire buffer to disk */
  213.     fp -> _update = NO;                    /* clear update flag */
  214.     return OK;
  215. }
  216. /*
  217.     sets '_nxtbyt' of 'fp' to 'offset' (a long int) from
  218. 'origin' , returns offset.
  219. */
  220.  
  221. unsigned    /* returns (long int) offset, -1 on error */
  222. lseek(fp, offset, origin)
  223. RFILE *fp;
  224. char *offset;
  225. int origin;
  226. {
  227.     unsigned sector, byt;
  228.     char longint[4], os[4], os2[4], lsecsiz[4];
  229.     unsigned rseek(), rcfsiz();
  230.     char *ltell();
  231.  
  232.     itol(lsecsiz, SECSIZ);                    /* set logical sector size */
  233.  
  234.     if (origin == 0) {                            /* from beginning of file */
  235.         movmem(offset, os, 4);                    /* make local copy */
  236.     }
  237.     else if (origin == 1) {
  238.         ladd(os, offset, ltell(fp, longint));    /* pres pos + offset to os */
  239.     }
  240.     else if (origin == 3) {                        /* ascii offset from start */
  241.         atol(os, offset);
  242.     }
  243.     else if (origin == 4) {                        /* ascii from pres pos */
  244.         atol(os2, offset);
  245.         ladd(os, os2, ltell(fp, longint));        /* pres pos + offset to os */
  246.     }
  247.     else return ERROR;                            /* only legal orgs now */
  248.     if (os[3] | os[2]) return ERROR;            /* within legal range? */
  249.     ltou(§or, ldiv(longint, os, lsecsiz));    /* byte / secsiz = sectors */
  250.     ltou(&byt, lmod(longint, os, lsecsiz));        /* remainder = bytes */
  251.     ++sector;                                    /* reserve sec 0 for future */
  252.  
  253.     if ((sector >= fp->_frstsec) AND                /* if in buffer */
  254.         (sector < (fp->_frstsec + fp->_secs))) {
  255.         fp->_nxtbyt = (sector - fp->_frstsec)*SECSIZ
  256.             + byt + fp->_bufbase;                    /* point to it */
  257.         return offset;                                /* and return */
  258.     }
  259.     if (_rflush(fp) == ERROR) return ERROR;            /* else flush buf */
  260.     if (rseek(fp->_rfd, sector, 0) == ERROR) return ERROR;
  261.     fp->_frstsec = sector;                            /* seek sec in file, */
  262.     fp->_nxtbyt = byt + fp->_bufbase;                /* and init ptrs */
  263.     if (_fillbuf(fp) == ERROR) return ERROR;        /* fill buf */
  264.     return offset;